/*
The surface-physics project: http://code.google.com/p/surface-physics/
Adds real world physics based on the Bullet physics engine, to bases in the Orbiter space
flight simulation software.

Written by Abhijit Nandy
License : Apache License 2.0

Bump_3WheeledVehicle.h
BulletBase Attachment management directly from within Bump

Models a 3 wheeled vehicle.

TODO : This class should read the options section of an object from the physics file

*/


#pragma once


#include "BulletBaseVehicle.h"
#include "../Terrain/Bump_TerrainPatch.h"

#include "../BulletBase/Bump_BaseObject.h"
#include "../Visualizer/GL_ShapeDrawer.h"


/**
 * The Bump_Attachment to create and manage a BulletBase
 */
class Bump_3WheeledVehicle : public Bump_BaseObject
{
	static DerivedRegister<Bump_3WheeledVehicle> reg;


	//Position wrt base, should this be updated every step ?
	VECTOR3 rposStartingVesselPos, gposVessel;

	double lng, lat, rad;;

	//Mesh handles, light handles, animation handles, other Orbiter primitives etc here

	//The attached VESSEL's pointer
	VESSEL3 *vAttached;
	BulletBaseVehicle *bbv;

	//Main Attachment point to a BulletBase(only 1 controlling BulletBase possible)
	ATTACHMENTHANDLE atVessel, atBase;

	//Raycast vehicle specific
	btRigidBody 		*m_carChassis;
	btVehicleRaycaster  *m_vehicleRayCaster;
	btRaycastVehicle	*m_vehicle;
	btRaycastVehicle::btVehicleTuning	m_tuning; //used to tune wheels, do not remove
	btCollisionShape	*m_wheelShape;
	btCollisionShape	*chassisBoxShape;
	btCompoundShape 	*compoundChassisShape;
	btScalar 			mass;

	//Rendering OpenGL object
	GL_ShapeDrawer* m_ShapeDrawer;

	//The position of this object in the PhysicsEngine rendering objects list
	//Useful when de-registering this object
	RenderObjectList::iterator renderFuncPos;


	/**
	 * Vehicle and wheel properties, these are wrapped inside the class rather
	 * than keeping them global to prevent interference with any other vehicle objects
	 */

	//Engine parameters
	float	maxEngineForce;//this should be engine/velocity dependent
	float	maxBreakingForce;
	float	gBreakingForce;
	float	gVehicleSteering;
	float	gEngineForce;

	//Transmission : simple gear model which varies engine force only
	int 	max_gear; //Reverse and neutral indicated by 'R' & 'N'
	int 	min_gear;
	int 	m_gear;

	//Steering parameters
	float	steeringIncrement;
	float	steeringClamp;

	/**
	 * Wheel parameters : Wheels continue to penetrate triangle mesh, not because of physics model,
	 * but because wheel mesh and physics wheel not aligned(physics wheel is more inwards,
	 * collision mesh wheel more outwards : there is actually no penetration)
	 */
	float	wheelRadius;
	float	wheelWidth;	 //actual width is 2.364(twice)
	float	wheelFriction;
	float	wheelFwdBackDist;
	float   wheelLeftRightDist;
	float	connectionHeight;
	int 	rightIndex;
	int 	upIndex;
	int 	forwardIndex;
	btVector3 wheelDirectionCS0;
	btVector3 wheelAxleCS;

	//Suspension parameters
	float	suspensionStiffness;
	float	suspensionDamping;
	float	suspensionCompression;
	float	rollInfluence;//1.0f;
	float 	suspensionRestLength;

	//Heights and initial location
	float 	initialVehicleHeight; //Height from which vehicle is dropped on terrain at physics start
	float 	chassisHeight; //Height of chassis above vehicle origin
	float 	chassisHalfLength;
	float 	chassisHalfWidth;
	float 	chassisHalfHeight;


	//Supporting terrain
	Bump_TerrainPatch *ground;



public:


	Bump_3WheeledVehicle();
	virtual ~Bump_3WheeledVehicle();

	//Main control functions
	int		init(Bump_BulletBase *bb, char *strObjName,  OBJHANDLE hObj = NULL);
	int		prestep(double SimT, double SimDT, double MJD);
	int		poststep(double SimT, double SimDT, double MJD);
	int		renderme(void);
	int		reset();
	int 	exit();

	//Utility stuff
	int 	readPhysicsFile(); //called during init() to read certain properties
	int		attachOrbiterVESSEL();
	int 	detachOrbiterVESSEL();
	int		createBulletRigidBody();
	int		destroyBulletRigidBody();
	int		processCommand();

	//Gets the transforms for this object, used to debug
	void	getTransforms(void);

};
